home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / iTunes Dock Dance Plugin / source / DockDancePlugIn.c < prev   
Encoding:
C/C++ Source or Header  |  2001-06-23  |  18.0 KB  |  677 lines

  1. /*
  2.     File:        iTVPlugIn.c
  3.  
  4.     Contains:    visual plug-in for iTunes
  5.  
  6.     Written by:    Developer Technical Support
  7.  
  8.     Copyright:    Copyright ©2001 Apple Computer,Inc.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <1>     4/17/01    DTS     first checked in.
  13. */
  14.  
  15. /**\
  16. |**|    includes
  17. \**/
  18.  
  19. #include "iTunesVisualAPI.h"
  20. #include <CGRemoteOperation.h>
  21.  
  22. /**\
  23. |**|    typedef's, struct's, enum's, etc.
  24. \**/
  25.  
  26. #define kTVisualPluginName                "\pDockDancePlugIn"
  27. #define    kTVisualPluginCreator            'hook'
  28.  
  29. #define    kTVisualPluginMajorVersion        1
  30. #define    kTVisualPluginMinorVersion        0
  31. #define    kTVisualPluginReleaseStage        finalStage
  32. #define    kTVisualPluginNonFinalRelease    0
  33. #define kStart                             10
  34. static Rect gDockRect;
  35. static Boolean gStop = true;
  36.  
  37. CGEventErr (*CGPostMouseEventFctPtr)    ( CGPoint, boolean_t, CGButtonCount, boolean_t, ...) =0;
  38.  
  39. CGEventErr (*CGSetLocalEventsSuppressionIntervalFctPtr)(CFTimeInterval seconds) = 0;
  40. void (*CGContextFillRectsFctPtr)(CGContextRef,const CGRect [],size_t) = 0;
  41. void (*CGContextSetRGBFillColorFctPtr)(CGContextRef, float, float, float, float)=0;
  42. void (*CGContextFlushFctPtr)(CGContextRef ctx) = 0;
  43. void (*CGContextScaleCTMFctPtr)(  CGContextRef   ctx,  float          sx,  float          sy) =0;
  44. void (*CGContextTranslateCTMFctPtr)(  CGContextRef   ctx,  float          sx,  float          sy) =0;
  45. void (*CGContextRotateCTMFctPtr)(  CGContextRef   ctx,  float          sx) =0;
  46.  
  47. typedef struct VisualPluginData {
  48.     void *                appCookie;
  49.     ITAppProcPtr        appProc;
  50.  
  51.     ITFileSpec            pluginFileSpec;
  52.     
  53.     CGrafPtr            destPort;
  54.     Rect                destRect;
  55.     CGContextRef        destContext;
  56.     OptionBits            destOptions;
  57.     UInt32                destBitDepth;
  58.  
  59.     RenderVisualData    renderData;
  60.     UInt32                renderTimeStampID;
  61.     
  62.     ITTrackInfo            trackInfo;
  63.     ITStreamInfo        streamInfo;
  64.  
  65.     Boolean                playing;
  66.     Boolean                padding[3];
  67.  
  68. //    Plugin-specific data
  69.  
  70.     GWorldPtr            offscreen;
  71.     UInt32                 position;
  72.     Boolean             idling;
  73.     UInt32                previousMaxIndex;
  74.     UInt32                currentMaxIndex;
  75.     UInt32                previousMaxValue;
  76.     UInt32                currentMaxValue;
  77. } VisualPluginData;
  78.  
  79.  
  80. #define SET_PIXEL(pm,h,v,c) \
  81.             { RGBForeColor(c);MoveTo(h,v);Line(1,0);}
  82.  
  83. /**\
  84. |**|    local (static) globals
  85. \**/
  86.  
  87. static CGrafPtr    gSavePort;
  88. static GDHandle    gSaveDevice;
  89. static SInt16    gLine = 0;
  90. static CFBundleRef gCGBundle =0;
  91. static float values[kVisualNumSpectrumEntries];
  92.  
  93. /**\
  94. |**|    exported function prototypes
  95. \**/
  96.  
  97. extern OSStatus iTunesPluginMain(OSType message,PluginMessageInfo *messageInfo,void *refCon);
  98.  
  99. /**\
  100. |**|    static functions
  101. \**/
  102.  
  103. //    MemClear
  104. static void MemClear(LogicalAddress dest,SInt32 length)
  105. {
  106.     register unsigned char    *ptr;
  107.  
  108.     ptr = (unsigned char*) dest;
  109.     
  110.     while (length-- > 0)
  111.         *ptr++ = 0;
  112. }
  113.  
  114.  void InitCoreGraphicFunctions()
  115. {
  116.     gCGBundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.CoreGraphics"));
  117.  
  118.     CGPostMouseEventFctPtr = (CGEventErr(*)( CGPoint, boolean_t, CGButtonCount, boolean_t, ...))
  119.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGPostMouseEvent"));
  120.  
  121.     CGSetLocalEventsSuppressionIntervalFctPtr =  (CGEventErr(*)( CFTimeInterval))
  122.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGSetLocalEventsSuppressionInterval"));
  123.  
  124.     CGContextFillRectsFctPtr =  (void(*)( CGContextRef,const CGRect [],size_t))
  125.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGContextFillRects"));
  126.  
  127.     CGContextSetRGBFillColorFctPtr = (void (*)(CGContextRef, float, float, float, float))
  128.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGContextSetRGBFillColor"));
  129.                 
  130.     CGContextFlushFctPtr =  (void (*)(CGContextRef ctx) )
  131.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGContextFlush"));
  132.  
  133.     CGContextTranslateCTMFctPtr = (void (*)(CGContextRef, float,  float))
  134.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGContextTranslateCTM"));
  135.     CGContextRotateCTMFctPtr = (void (*)(CGContextRef, float))
  136.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGContextRotateCTM"));
  137.     CGContextScaleCTMFctPtr = (void (*)(CGContextRef, float, float))
  138.                 CFBundleGetFunctionPointerForName(gCGBundle, CFSTR("CGContextScaleCTM"));
  139.  
  140.  
  141. }
  142.  
  143. // ProcessRenderData
  144.  
  145.  void ProcessRenderData(VisualPluginData *visualPluginData,const RenderVisualData *renderData)
  146. {
  147.     SInt16        index;
  148.     SInt32        channel;
  149.  
  150.     if (renderData == nil)
  151.     {
  152.         MemClear(&visualPluginData->renderData,sizeof(visualPluginData->renderData));
  153.         return;
  154.     }
  155.  
  156.     visualPluginData->renderData = *renderData;
  157.     
  158.     visualPluginData->previousMaxIndex = visualPluginData->currentMaxIndex;    
  159.     visualPluginData->previousMaxValue = visualPluginData->currentMaxValue;
  160.     
  161.     for (channel = 0;channel < renderData->numSpectrumChannels;channel++)
  162.     {
  163.         visualPluginData->currentMaxValue = renderData->spectrumData[channel][0];
  164.         visualPluginData->currentMaxIndex = 0;
  165.         for (index = 1; index < kVisualNumSpectrumEntries; index++)
  166.         {
  167.             UInt8        value;
  168.             value = renderData->spectrumData[channel][index];
  169.     
  170.             if (value > visualPluginData->currentMaxValue)
  171.             {
  172.                 visualPluginData->currentMaxValue = value;
  173.                 visualPluginData->currentMaxIndex = index;
  174.             }
  175.         }
  176.     }
  177.     
  178. }
  179.  
  180. /*
  181.     RenderVisualPort
  182. */
  183.  void RenderVisualPort(VisualPluginData *visualPluginData, Boolean playing)
  184. {
  185.  
  186.     CGrafPtr port;
  187.     static CGContextRef context = NULL;
  188.     GDHandle dev;
  189.     UInt32 spectIndex;
  190.     RgnHandle rgn;
  191.     RGBColor black = {0,0,0};
  192.     CGRect   rects[32];
  193.     long index;
  194.     CGRect     baseRect = {{0,0}, {0,0}};
  195.     Rect bounds = visualPluginData->destRect;
  196.     UInt32 width;
  197.     
  198.     static float directionX = 1;
  199.     static float directionY = 1;
  200.     static float angle = 2;
  201.     static float scalingX = 0.9;
  202.     static float scalingY = 0.9;
  203.  
  204.     long change = TickCount();
  205.         
  206.     if (context == NULL)    
  207.         CreateCGContextForPort(visualPluginData->destPort,&context);
  208.         
  209.     if (context == NULL)
  210.         return;    
  211.         
  212. /*            
  213.     if (change % 2)
  214.         directionX = -directionX;
  215.  
  216.     if (change % 3)
  217.         directionY = -directionY;
  218.  
  219.     if (change % 7)
  220.         angle = -angle;
  221.  
  222.     if (change % 13)
  223.         scalingX *= 0.3;
  224.         
  225.     if (change % 3)
  226.         scalingX = 0.9;
  227.  
  228.     if (change % 2)
  229.         scalingY *= 0.3;
  230.         
  231.     if (change % 11)
  232.         scalingY = 0.9;
  233.  
  234.  
  235.     CGContextTranslateCTMFctPtr(context, directionX, directionY);
  236.     CGContextRotateCTMFctPtr(context, angle);
  237.     CGContextScaleCTMFctPtr(context, scalingX, scalingY);
  238. */
  239.     if( visualPluginData->playing == false)
  240.         return;
  241.     
  242.     GetGWorld(&port, &dev);
  243.     SetPort(visualPluginData->destPort);
  244.     RGBBackColor(&black);
  245.     EraseRect(&visualPluginData->destRect);
  246.     SetGWorld(port, dev);
  247.  
  248.     rgn = NewRgn();
  249.     RectRgn( rgn,&visualPluginData->destRect);
  250.     ClipCGContextToRegion(context,& visualPluginData->destRect, rgn);
  251.     DisposeRgn(rgn);
  252.  
  253.     
  254.     width = (bounds.right - bounds.left) / 32;
  255.  
  256.     baseRect.origin.x = 10;
  257.     baseRect.origin.y = 40;
  258.     baseRect.size.width = width;
  259.     
  260.     for (spectIndex = 0, index =0; spectIndex < kVisualNumSpectrumEntries; spectIndex+= (kVisualNumSpectrumEntries/32), index++)
  261.     {
  262.         UInt8        value;
  263.         baseRect.origin.x += width;
  264.         
  265.         value = visualPluginData->renderData.spectrumData[0][spectIndex];
  266.  
  267.         baseRect.size.height = (((float)value)/255.0) * (bounds.bottom - bounds.top-20);
  268.  
  269.         rects[index].origin.x = baseRect.origin.x;
  270.         rects[index].origin.y = baseRect.origin.y;
  271.         rects[index].size.width = baseRect.size.width;
  272.         rects[index].size.height = baseRect.size.height;
  273.  
  274.     }
  275.  
  276.  
  277.     CGContextSetRGBFillColorFctPtr(context, 0,1,0,1);
  278.     CGContextFillRectsFctPtr(context, rects, 30);
  279.     CGContextFlushFctPtr(context);
  280.  
  281.     if (CGPostMouseEventFctPtr == NULL)
  282.         return; 
  283.         
  284.     if (gStop == true)
  285.         return;    
  286.         
  287.     if (playing == true)
  288.     {
  289.         static float invert = 0;
  290.  
  291.         if ((visualPluginData->currentMaxIndex == visualPluginData->previousMaxIndex) &&
  292.             (visualPluginData->currentMaxValue < visualPluginData->previousMaxValue))
  293.         {
  294.             CGPoint pos;
  295.             pos.x = 0;
  296.             pos.y = 0;
  297.         
  298. //            CGPostMouseEventFctPtr(pos,true, 1, false );
  299.         } 
  300.         else
  301.         {
  302.             CGPoint pos;
  303.             if ( visualPluginData->currentMaxIndex != visualPluginData->previousMaxIndex )
  304.                 values[visualPluginData->previousMaxIndex] = 0;
  305.                 
  306.             values[visualPluginData->currentMaxIndex] += visualPluginData->currentMaxValue/2;
  307.  
  308.             pos.x = (invert-(((float)(visualPluginData->currentMaxIndex))/((float)kVisualNumSpectrumEntries)) )
  309.                     * (gDockRect.right-500)+250;
  310.         
  311.             if (values[visualPluginData->currentMaxIndex] < 128)
  312.             {
  313.                 pos.y = gDockRect.bottom-10;
  314.             }
  315.             else
  316.             {
  317.                 pos.y = gDockRect.bottom-138;
  318.  
  319.                 if (invert == 0)
  320.                     invert = 1;
  321.                 else
  322.                     invert = 0;
  323.             }        
  324.  
  325.             CGPostMouseEventFctPtr(pos,true, 1, false );
  326.         }
  327.     
  328.     }
  329.     else
  330.     {
  331.         static SInt8 direction = 30;
  332.         
  333.         if ((visualPluginData->position > (gDockRect.right-kStart)))
  334.             direction = -direction;
  335.                 
  336.         if (visualPluginData->position < (gDockRect.left+kStart))
  337.         {
  338.             direction = -direction;
  339.             visualPluginData->position = (gDockRect.left+kStart);
  340.         }
  341.         
  342.         {
  343.             CGPoint pos;
  344.             pos.x = visualPluginData->position;
  345.             pos.y = gDockRect.bottom-10;
  346.         
  347.         
  348.             CGPostMouseEventFctPtr(pos,true, 1, false );
  349.         }
  350.         
  351.         
  352.         
  353.         
  354.         visualPluginData->position += direction;
  355.     }
  356. }
  357.  
  358. /*
  359.     ResetRenderData
  360. */
  361. static void ResetRenderData(VisualPluginData *visualPluginData)
  362. {
  363.     MemClear(&visualPluginData->renderData,sizeof(visualPluginData->renderData));
  364.  
  365.     visualPluginData->previousMaxIndex = visualPluginData->currentMaxIndex = 0;
  366. }
  367.  
  368. /*
  369.     VisualPluginHandler
  370. */
  371.  OSStatus VisualPluginHandler(OSType message,VisualPluginMessageInfo *messageInfo,void *refCon)
  372. {
  373.     OSStatus            status;
  374.     VisualPluginData *    visualPluginData;
  375.     
  376.     visualPluginData = (VisualPluginData*) refCon;
  377.     
  378.     status = noErr;
  379.  
  380.     switch (message)
  381.     {
  382.         /*
  383.             Sent when the visual plugin is registered.  The plugin should do minimal
  384.             memory allocations here.  The resource fork of the plugin is still available.
  385.         */        
  386.         case kVisualPluginInitMessage:
  387.         {
  388.             visualPluginData = (VisualPluginData*) NewPtrClear(sizeof(VisualPluginData));
  389.             if (visualPluginData == nil)
  390.             {
  391.                 status = memFullErr;
  392.                 break;
  393.             }
  394.  
  395.             visualPluginData->appCookie    = messageInfo->u.initMessage.appCookie;
  396.             visualPluginData->appProc    = messageInfo->u.initMessage.appProc;
  397.  
  398.             /* Remember the file spec of our plugin file. We need this so we can open our resource fork during */
  399.             /* the configuration message */
  400.             
  401.             status = PlayerGetPluginFileSpec(visualPluginData->appCookie,visualPluginData->appProc,&visualPluginData->pluginFileSpec);
  402.  
  403.             messageInfo->u.initMessage.refCon    = (void*) visualPluginData;
  404.             break;
  405.         }
  406.             
  407.         /*
  408.             Sent when the visual plugin is unloaded
  409.         */        
  410.         case kVisualPluginCleanupMessage:
  411.             if (visualPluginData != nil)
  412.                 DisposePtr((Ptr)visualPluginData);
  413.             break;
  414.             
  415.         /*
  416.             Sent when the visual plugin is enabled.  iTunes currently enables all
  417.             loaded visual plugins.  The plugin should not do anything here.
  418.         */
  419.         case kVisualPluginEnableMessage:
  420.         case kVisualPluginDisableMessage:
  421.             break;
  422.  
  423.         /*
  424.             Sent if the plugin requests idle messages.  Do this by setting the kVisualWantsIdleMessages
  425.             option in the RegisterVisualMessage.options field.
  426.         */
  427.         case kVisualPluginIdleMessage:
  428.             RenderVisualPort(visualPluginData, visualPluginData->playing);
  429.             break;
  430.                     
  431.         /*
  432.             Sent when iTunes is going to show the visual plugin in a port.  At
  433.             this point,the plugin should allocate any large buffers it needs.
  434.         */
  435.         case kVisualPluginShowWindowMessage:
  436.             visualPluginData->destOptions = messageInfo->u.showWindowMessage.options;
  437.             visualPluginData->destPort = messageInfo->u.showWindowMessage.port;
  438.             visualPluginData->destRect = messageInfo->u.showWindowMessage.drawRect;
  439.  
  440.             break;
  441.             
  442.         /*
  443.             Sent when iTunes is no longer displayed.
  444.         */
  445.         case kVisualPluginHideWindowMessage:
  446.  
  447.             MemClear(&visualPluginData->trackInfo,sizeof(visualPluginData->trackInfo));
  448.             MemClear(&visualPluginData->streamInfo,sizeof(visualPluginData->streamInfo));
  449.             break;
  450.         
  451.         /*
  452.             Sent when iTunes needs to change the port or rectangle of the currently
  453.             displayed visual.
  454.         */
  455.         case kVisualPluginSetWindowMessage:
  456.             visualPluginData->destOptions = messageInfo->u.setWindowMessage.options;
  457.             visualPluginData->destPort = messageInfo->u.showWindowMessage.port;
  458.             visualPluginData->destRect = messageInfo->u.showWindowMessage.drawRect;
  459.             
  460.             break;
  461.         
  462.         /*
  463.             Sent for the visual plugin to render a frame.
  464.         */
  465.         case kVisualPluginRenderMessage:
  466.             visualPluginData->renderTimeStampID    = messageInfo->u.renderMessage.timeStampID;
  467.             ProcessRenderData(visualPluginData,messageInfo->u.renderMessage.renderData);
  468.                 
  469.             RenderVisualPort(visualPluginData,visualPluginData->playing);
  470.             break;
  471.  
  472.         /*
  473.             Sent in response to an update event.  The visual plugin should update
  474.             into its remembered port.  This will only be sent if the plugin has been
  475.             previously given a ShowWindow message.
  476.         */    
  477.         case kVisualPluginUpdateMessage:
  478.             break;
  479.         
  480.         /*
  481.             Sent when the player starts.
  482.         */
  483.         case kVisualPluginPlayMessage:
  484.             if (messageInfo->u.playMessage.trackInfo != nil)
  485.                 visualPluginData->trackInfo = *messageInfo->u.playMessage.trackInfo;
  486.             else
  487.                 MemClear(&visualPluginData->trackInfo,sizeof(visualPluginData->trackInfo));
  488.  
  489.             if (messageInfo->u.playMessage.streamInfo != nil)
  490.                 visualPluginData->streamInfo = *messageInfo->u.playMessage.streamInfo;
  491.             else
  492.                 MemClear(&visualPluginData->streamInfo,sizeof(visualPluginData->streamInfo));
  493.         
  494.             visualPluginData->playing = true;
  495.             HideCursor();
  496.             break;
  497.  
  498.         /*
  499.             Sent when the player changes the current track information.  This
  500.             is used when the information about a track changes,or when the CD
  501.             moves onto the next track.  The visual plugin should update any displayed
  502.             information about the currently playing song.
  503.         */
  504.         case kVisualPluginChangeTrackMessage:
  505.             if (messageInfo->u.changeTrackMessage.trackInfo != nil)
  506.                 visualPluginData->trackInfo = *messageInfo->u.changeTrackMessage.trackInfo;
  507.             else
  508.                 MemClear(&visualPluginData->trackInfo,sizeof(visualPluginData->trackInfo));
  509.  
  510.             if (messageInfo->u.changeTrackMessage.streamInfo != nil)
  511.                 visualPluginData->streamInfo = *messageInfo->u.changeTrackMessage.streamInfo;
  512.             else
  513.                 MemClear(&visualPluginData->streamInfo,sizeof(visualPluginData->streamInfo));
  514.             break;
  515.  
  516.         /*
  517.             Sent when the player stops.
  518.         */
  519.         case kVisualPluginStopMessage:
  520.             visualPluginData->playing = false;
  521.             ResetRenderData(visualPluginData);
  522.             visualPluginData->position = 512;
  523.  
  524.             RenderVisualPort(visualPluginData,visualPluginData->playing);
  525.             ShowCursor();
  526.             break;
  527.         
  528.         /*
  529.             Sent when the player changes position.
  530.         */
  531.         case kVisualPluginSetPositionMessage:
  532.             break;
  533.  
  534.         /*
  535.             Sent when the player pauses.  iTunes does not currently use pause or unpause.
  536.             A pause in iTunes is handled by stopping and remembering the position.
  537.         */
  538.         case kVisualPluginPauseMessage:
  539.             visualPluginData->playing = false;
  540.  
  541.             ResetRenderData(visualPluginData);
  542.             visualPluginData->position = 512;
  543.  
  544.             RenderVisualPort(visualPluginData,visualPluginData->playing);
  545.             ShowCursor();
  546.             break;
  547.             
  548.         /*
  549.             Sent when the player unpauses.  iTunes does not currently use pause or unpause.
  550.             A pause in iTunes is handled by stopping and remembering the position.
  551.         */
  552.         case kVisualPluginUnpauseMessage:
  553.             visualPluginData->playing = true;
  554.  
  555.             break;
  556.         
  557.         /*
  558.             Sent to the plugin in response to a MacOS event.  The plugin should return noErr
  559.             for any event it handles completely,or an error (unimpErr) if iTunes should handle it.
  560.         */
  561.         case kVisualPluginEventMessage:
  562.             {
  563.                 EventRecord* tEventPtr = messageInfo->u.eventMessage.event;
  564.                 if ((tEventPtr->what == keyDown) || (tEventPtr->what == autoKey))
  565.                 {    // charCodeMask,keyCodeMask;
  566.                     char theChar = tEventPtr->message & charCodeMask;
  567.  
  568.                     switch (theChar)
  569.                     {
  570.                     case    'q':
  571.                     case    'Q':
  572.                         gStop = !gStop;
  573.                         status = noErr;
  574.                         break;
  575.                     case    'f':
  576.                     case    'F':
  577.                         status = noErr;
  578.                         break;
  579.                     default:
  580.                         status = unimpErr;
  581.                         break;
  582.                     }
  583.                 }
  584.                 else
  585.                     status = unimpErr;
  586.             }
  587.             break;
  588.  
  589.         default:
  590.             status = unimpErr;
  591.             break;
  592.     }
  593.     return status;    
  594. }
  595.  
  596. /*
  597.     RegisterVisualPlugin
  598. */
  599.  OSStatus RegisterVisualPlugin(PluginMessageInfo *messageInfo)
  600. {
  601.     OSStatus            status;
  602.     PlayerMessageInfo    playerMessageInfo;
  603.     Str255                pluginName = kTVisualPluginName;
  604.         
  605.     MemClear(&playerMessageInfo.u.registerVisualPluginMessage,sizeof(playerMessageInfo.u.registerVisualPluginMessage));
  606.     
  607.     BlockMoveData((Ptr)&pluginName[0],(Ptr)&playerMessageInfo.u.registerVisualPluginMessage.name[0],pluginName[0] + 1);
  608.  
  609.     SetNumVersion(&playerMessageInfo.u.registerVisualPluginMessage.pluginVersion,kTVisualPluginMajorVersion,kTVisualPluginMinorVersion,kTVisualPluginReleaseStage,kTVisualPluginNonFinalRelease);
  610.  
  611.     playerMessageInfo.u.registerVisualPluginMessage.options                    = 0;//kVisualWantsIdleMessages ;
  612.     playerMessageInfo.u.registerVisualPluginMessage.handler                    = VisualPluginHandler;
  613.     playerMessageInfo.u.registerVisualPluginMessage.registerRefCon            = 0;
  614.     playerMessageInfo.u.registerVisualPluginMessage.creator                    = kTVisualPluginCreator;
  615.     
  616.     playerMessageInfo.u.registerVisualPluginMessage.timeBetweenDataInMS        = 0xF; // 16 milliseconds = 1 Tick,0xFFFFFFFF = Often as possible.
  617.     playerMessageInfo.u.registerVisualPluginMessage.numWaveformChannels        = 2;
  618.     playerMessageInfo.u.registerVisualPluginMessage.numSpectrumChannels        = 2;
  619.     
  620.     playerMessageInfo.u.registerVisualPluginMessage.minWidth                = 64;
  621.     playerMessageInfo.u.registerVisualPluginMessage.minHeight                = 64;
  622.     playerMessageInfo.u.registerVisualPluginMessage.maxWidth                = 32767;
  623.     playerMessageInfo.u.registerVisualPluginMessage.maxHeight                = 32767;
  624.     playerMessageInfo.u.registerVisualPluginMessage.minFullScreenBitDepth    = 0;
  625.     playerMessageInfo.u.registerVisualPluginMessage.maxFullScreenBitDepth    = 0;
  626.     playerMessageInfo.u.registerVisualPluginMessage.windowAlignmentInBytes    = 0;
  627.     
  628.     status = PlayerRegisterVisualPlugin(messageInfo->u.initMessage.appCookie,messageInfo->u.initMessage.appProc,&playerMessageInfo);
  629.         
  630.  
  631.  
  632.     return status;
  633.     
  634. }
  635.  
  636. /**\
  637. |**|    main entrypoint
  638. \**/
  639.  
  640. OSStatus iTunesPluginMain(OSType message,PluginMessageInfo *messageInfo,void *refCon)
  641. {
  642.     OSStatus        status;
  643.     
  644.     (void) refCon;
  645.     
  646.     switch (message)
  647.     {
  648.         case kPluginInitMessage:
  649.         {
  650.             Rect avail;
  651.             GDHandle screen = GetMainDevice();
  652.  
  653.             status = RegisterVisualPlugin(messageInfo);
  654.             
  655.             MemClear(values, sizeof(values));
  656.             
  657.             InitCoreGraphicFunctions();
  658.             
  659.             CGSetLocalEventsSuppressionIntervalFctPtr(1.0/50.0);
  660.             GetAvailableWindowPositioningBounds(screen,&avail);
  661.             SetRect(&gDockRect, (*screen)->gdRect.left, avail.bottom, 
  662.                                 (*screen)->gdRect.right, (*screen)->gdRect.bottom);
  663.             break;
  664.         }
  665.         case kPluginCleanupMessage:
  666.             CFRelease(gCGBundle);
  667.             status = noErr;
  668.             break;
  669.             
  670.         default:
  671.             status = unimpErr;
  672.             break;
  673.     }
  674.     
  675.     return status;
  676. }
  677.